package com.fengwk.support.proxy.http;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.fengwk.support.exception.BaseException;
import com.fengwk.support.proxy.http.annotation.HttpClient;
import com.fengwk.support.util.JsonUtils;
import com.fengwk.support.util.MapUtils;
import com.fengwk.support.util.ReflectUtils;
import com.fengwk.support.util.StringUtils;
import com.fengwk.support.util.TypeUtils;
import com.fengwk.support.util.WebUtils;

public class EncodeImpl implements Encode {

	@Autowired
	private HttpServletRequest request;
	
	@Override
	public Request encode(
			HttpClient httpClient, 
			RequestMapping requestMapping, 
			PostMapping postMapping,
			GetMapping getMapping, 
			Map<Integer, PathVariable> indexPathVariableMap,
			Map<Integer, RequestParam> indexRequestParamMap, 
			Object[] args) {
		Request request = new Request();
		request.setUrl(buildUrl(httpClient, requestMapping, postMapping, getMapping, indexPathVariableMap, args));
		request.setParams(buildParams(indexRequestParamMap, args));
		return request;
	}

	private String buildUrl(
			HttpClient httpClient, 
			RequestMapping requestMapping, 
			PostMapping postMapping,
			GetMapping getMapping,
			Map<Integer, PathVariable> indexPathVariableMap,
			Object[] args) {
		StringBuffer sb = new StringBuffer();
		
		if (httpClient.selfUrl()) {
			sb.append(WebUtils.getSelfUrl(request));
		} else if (StringUtils.isNotBlank(httpClient.staticUrl())) {
			sb.append(ReflectUtils.readStaticField(httpClient.staticUrl()));
		} else {
			sb.append(httpClient.url());
		}
		sb.append(HttpProxyUtils.getValue(httpClient.path(), httpClient.value()));
		if (requestMapping != null) {
			sb.append(HttpProxyUtils.getValue(requestMapping.path(), requestMapping.value()));
		} else if (postMapping != null) {
			sb.append(HttpProxyUtils.getValue(postMapping.path(), postMapping.value()));
		} else if (getMapping != null) {
			sb.append(HttpProxyUtils.getValue(getMapping.path(), getMapping.value()));
		}
		String url = sb.toString();
		if (MapUtils.isNotBlank(indexPathVariableMap)) {
			Iterator<Entry<Integer, PathVariable>> parameterPathVariableIt = indexPathVariableMap.entrySet().iterator();
			while (parameterPathVariableIt.hasNext()) {
				Entry<Integer, PathVariable> parameterPathVariableEntry = parameterPathVariableIt.next();
				Integer index = parameterPathVariableEntry.getKey();
				PathVariable pathVariable = parameterPathVariableEntry.getValue();
				String paramName = HttpProxyUtils.getValue(pathVariable.name(), pathVariable.value());
				Object param = args[index];
				if (pathVariable.required() && param == null) {
					throw new BaseException(paramName + " 不能为空");
				}
				url = url.replace("{" + paramName + "}", param + "");
			}
		}
		return url;
	}
	
	private Map<String, String> buildParams(
			Map<Integer, RequestParam> indexRequestParamMap, 
			Object[] args) {
		Map<String, String> params = new HashMap<String, String>();
		if (MapUtils.isNotBlank(indexRequestParamMap)) {
			Iterator<Entry<Integer, RequestParam>> parameterRequestParamIt = indexRequestParamMap.entrySet().iterator();
			while (parameterRequestParamIt.hasNext()) {
				Entry<Integer, RequestParam> parameterRequestParamEntry = parameterRequestParamIt.next();
				Integer index = parameterRequestParamEntry.getKey();
				RequestParam requestParam = parameterRequestParamEntry.getValue();
				String paramName = HttpProxyUtils.getValue(requestParam.name(), requestParam.value());
				Object param = args[index];
				if (requestParam.required() && param == null) {
					throw new BaseException(paramName + " 不能为空");
				}
				if (param != null 
						&& !TypeUtils.isType(param.getClass(), String.class) 
						&& !TypeUtils.isType(param.getClass(), Integer.class) 
						&& !TypeUtils.isType(param.getClass(), Long.class) 
						&& !TypeUtils.isType(param.getClass(), Short.class) 
						&& !TypeUtils.isType(param.getClass(), Double.class) 
						&& !TypeUtils.isType(param.getClass(), Float.class) 
						&& !TypeUtils.isType(param.getClass(), Character.class) 
						&& !TypeUtils.isType(param.getClass(), Boolean.class) 
						&& !TypeUtils.isType(param.getClass(), Byte.class) 
						&& !TypeUtils.isType(param.getClass(), int.class) 
						&& !TypeUtils.isType(param.getClass(), long.class) 
						&& !TypeUtils.isType(param.getClass(), short.class) 
						&& !TypeUtils.isType(param.getClass(), double.class) 
						&& !TypeUtils.isType(param.getClass(), float.class) 
						&& !TypeUtils.isType(param.getClass(), char.class) 
						&& !TypeUtils.isType(param.getClass(), boolean.class)
						&& !TypeUtils.isType(param.getClass(), byte.class)  
						) {
					param = JsonUtils.toJson(param);
				}
				params.put(paramName, param + "");
			}
		}
		return params;
	}
	
}
